//g++ max.cpp -o max -lespeak
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <time.h>
#include <errno.h>

//This is for making the FIFO's so that the process can communicate
#include <sys/stat.h>

//apt-get install libspeak dev
//apt-get install mbrola
//apt-get install mbrola-en1
#include <espeak/speak_lib.h>
#include <string.h>


#define FIFOFILE "/home/filitchp/maxFIFO"
#define MPLAYER_OPT " -slave -really-quiet -idle -loop 0 -fs"
#define VIDEO "/home/filitchp/santa-barbot/server/LLoyd.m4v"

void mp_connect(FILE** mplayer, std::string name);
void mp_seek(FILE* mp, int seek);
void mp_pause(FILE* mp);
void sleep(double wait);
void mp_skip(FILE* mp, double skip);
void mp_glitch(FILE* mp);
void mp_close(FILE* mp);
void es_init();
void es_say(const char* speech);
void demoscript(FILE* mp);
void max_say(FILE* mp, const char* speech);
void livemode(FILE* mp);
void max_send(const char* speech);
void max_mix(FILE* mp);
void max_drink(std::string drink);
void max_delivery(FILE* mp);
void mp_say(FILE* mp, const char* speech);

//This is the location % in the video of the mixing animation
int c_mixingpercentage = 54;
int c_delivery = 34;

int main(int argc, char* argv[]){

	FILE* mp;
	char* parameter;

	//Initialize Espeak
	es_init();
 
	//Parse input arguments
	for (int k = 1; k < argc; k++){

		parameter = argv[k];

		if (strstr(parameter,"-d")){
			mp_connect(&mp, VIDEO);
			demoscript(mp);
			mp_close(mp);
		}
		else if (strstr(parameter,"-s")){
			if (++k < argc){
				parameter = argv[k];
				max_send(parameter);
			}
		}
		else if (strstr(parameter, "-l")){
			mp_connect(&mp, VIDEO);
			livemode(mp);
			mp_close(mp);
		}
		else if (strstr(parameter, "-m")){
			max_send("mix");
		}
		else if (strstr(parameter, "-q")){
			if (++k < argc){
				parameter = argv[k];
				max_drink(parameter);
			}
		}
		else{
			std::cout << "try -say, -demo, or -live \n";
		}

		memset(parameter, 0, sizeof(parameter));

 	}


}

//Connects and configures mplayer, returns address of a stream
void mp_connect(FILE** mplayer, std::string name){

	std::string popenstr = "mplayer " + name + MPLAYER_OPT;
	char * popenchar;
	popenchar = new char[popenstr.size()+1];

	strcpy(popenchar, popenstr.c_str());

	//Start mplayer and put it in the pipe
	if   ( !(*mplayer = popen(popenchar, "w")) ){
		perror("mp pipe");
		exit(1);
	}

	//Make sure the pipe is packed
	fprintf(*mplayer, "osd 0\n");
	fprintf(*mplayer, "pause\n");

	fflush(*mplayer);
 }

//Seeks to a desired value as a percentage
void mp_seek(FILE* mp, int seek){

	fprintf(mp, "pause\n");
	fprintf(mp,"pausing_keep_force seek %d 1\n", seek);
	fprintf(mp,"pause\n");
	fflush(mp);

}

//skips back/forward by an amount in seconds
void mp_skip(FILE* mp, double skip){

     fprintf(mp,"pause\n");
     fprintf(mp,"pausing_keep_force seek %f 0\n", skip);
     fprintf(mp,"pause\n");
     fflush(mp);
}

//just a pause for now
void mp_pause(FILE* mp){

     fprintf(mp,"pause\n");
     fflush(mp);
}

//Sleeps, needed in this program
void sleep(double wait){

	clock_t waittill = clock() + (wait*(double)CLOCKS_PER_SEC);
	while (clock() < waittill)
	{
		//Twiddle
	}
}

//Tuning a glitch effect
//For this to work the video needs to be encoded to have frequent keyframes
//mencoder movie.avi -oac copy -ovc lavc -lavcopts keyint=3 -ofps 23.976 -o movie.avi

void mp_glitch(FILE* mp){

	for (int k = 0; k < 4; k++)
	{
	// These need to be offset... timing is dependant on good keyframes.
		mp_skip(mp, -0.6);
		sleep(0.6);
	}
}

//This closes everything out
void mp_close(FILE* mp){

	//Close the software
        fprintf(mp,"quit\n");

	//close the pipe
	pclose(mp);

}

void es_init(){

	espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,NULL,0);
	espeak_SetVoiceByName("en1");
	espeak_SetParameter(espeakRATE, 140, 0);
	espeak_SetParameter(espeakVOLUME, 500, 0);

}

void es_say(const char* speech){

	espeak_Synth(speech, strlen(speech) + 1,0, POS_CHARACTER,0, espeakCHARS_AUTO,NULL,NULL);
	espeak_Synchronize();
}

void mp_say(FILE* mp, const char* speech){
        //fprintf(mp,"osd 1");     
        //fprintf(mp,"osd_show_text %s 6 1", speech); 
        //fprintf(mp,"osd 0");
        //fflush(mp);
}

void max_say(FILE* mp, const char* speech){
	mp_seek(mp,0);
	mp_pause(mp);
	mp_say(mp, speech);
	es_say(speech);
	mp_seek(mp,0);
	mp_pause(mp);
}

void max_mix(FILE* mp){
	mp_pause(mp);
	mp_seek(mp,c_mixingpercentage);
	sleep(30.0);
	mp_pause(mp);
	mp_seek(mp, c_delivery);
	fflush(mp);
}

void max_delivery(FILE* mp){

	mp_pause(mp);
	mp_seek(mp,c_delivery);
	es_say("Ha Ha Ha");
	es_say("How was my delivery?");
	mp_pause(mp);
	fflush(mp);
}

void demoscript(FILE* mp){

	sleep(4.0);

	max_say(mp,"Hello, How are you today?");

	sleep(5.0);

	max_say(mp,"A gin and tonic for you sir");

	sleep(4.0);
}

//This mode is going to live, and wait for inputs from the MAXFIFO
void livemode(FILE* mp){

	std::ifstream instream;
	char line[256];
	bool quit = 0;
	int errorcatch;

	while(!quit)
	{

		mknod(FIFOFILE, S_IFIFO | 0666, 0);

		//This blocks, waits for a message
		instream.open(FIFOFILE,std::ios::app);

		if (instream.is_open())
		{
			//Get a line
			instream.getline(line,256);

			//say goodbye, switch to mix, or say it... yes I KNOW THIS IS UGLY
			//This is the WRONG WAY, may the programming gods have forgivness on my soul for what I have done
			if (strstr(line,"goodbye")){
				quit = 1;
			}
			else if (strstr(line,"mix")) {
				max_mix(mp);
			}
			else if (strstr(line,"delivery")) {
				max_delivery(mp);
			}
			else {
				std::cout<< line <<"\n";
				max_say(mp, line);
			}
			//Closes the stream and loops
 			instream.close();
		}

	}

	std::cout << "closing down.\n";

	instream.close();
}

void max_send(const char* speech)
{
	std::ofstream outstream;

	outstream.open(FIFOFILE,std::ios::app);

	if (outstream.is_open()){
		outstream << speech << "\n";
		outstream.flush();
		outstream.close();
		std::cout<<"Sent\n";
	}
	else {perror("Unable to open stream\n");}


}

void max_drink(std::string drink){
 // Verify drink name and talk about it  
  if (drink.compare("debugAll05") == 0)
  { 
    max_send("debug All 05, siiir");
  }
  else if (drink.compare("debugAll10") == 0)
  { 
    max_send("debug All 10, siiir");
  }
  else if (drink.compare("debugVodka") == 0)
  { 
    max_send("debug Vodka, comrade");
  }
  else if (drink.compare("debugRum") == 0)
  { 
    max_send("debug rum, mayttie");
  }
  else if (drink.compare("debugWhiskey") == 0)
  { 
    max_send("debug whiskey, siiir");
  }
  else if (drink.compare("debugGin") == 0)
  { 
    max_send("debug gin, chap");
  }
  else if (drink.compare("debugOj") == 0)
  { 
    max_send("debug Orange Juice, siiir");
  }
  else if (drink.compare("debugLime") == 0)
  { 
    max_send("debug Lime, mayttie");
  }
  else if (drink.compare("debugCoke") == 0)
  { 
    max_send("debug coke, siiir");
  }
  else if (drink.compare("debugGingerBeer") == 0)
  { 
    max_send("debug Ginger beer, siiir");
  }
  else if (drink.compare("screwdriver") == 0)
  { 
    max_send("All due respect sir, Keep those screwdrivers away from me");
    sleep(6.0);
    max_send("mix");
  }
  else if (drink.compare("keyWestScrewdriver") == 0)
  { 
    max_send("When I need a replacement screw, I ask for one");
    sleep(5.0);
    max_send("delivery");
    sleep(5.0);
    max_send("mix");
  }
  else if (drink.compare("moscowMule") == 0)
  { 
    max_send("In the future alcoholics anonynmous leads the resistance against drunk-net.");
    sleep(5.0);
    max_send(" Have another drink sir.");
    sleep(3.0);
    max_send("mix");
  }
  else if (drink.compare("brassMonkey") == 0)
  {
    max_send("If I serve one more of these and I will have violated the first law of robotics");
    sleep(6.0);
    max_send("delivery");
    sleep(3.0);
    max_send("mix");
  }
  else if (drink.compare("cubaLibre") == 0)
  {
    max_send("Brain the size of an entire fucking planet and I'm here making cocktails.");
    sleep(5.0);
    max_send("mix");
  }
  else if (drink.compare("rumAndCoke") == 0)
  {
    max_send("Rum and coke? Reeeeal original buddy");
    sleep(4.0);
    max_send("mix");
  }
  else if (drink.compare("vodkaOnTheRocks") == 0)
  {
	max_send("How do rural robots communicate?");
    	sleep(4.0);
	max_send("E. I. E..,, I O");
	sleep(4.0);
    	max_send("delivery");
    	sleep(2.0);
    	max_send("mix");
  }
  else if (drink.compare("rumOnTheRocks") == 0)
  {
    max_send("Yaaaaaaaaaaaaaaaaawn");
    sleep(3.0);
    max_send("mix");
  }
  else if (drink.compare("whiskeyOnTheRocks") == 0)
  {
    max_send("If I serve one more of these and I will have violated the first law of robotics");
    sleep(6.0);
    max_send("delivery");
    sleep(3.0);
    max_send("mix");
  }
  else if (drink.compare("ginOnTheRocks") == 0)
  {
    max_send("I'm not a robot, you're a robot");
    sleep(5.0);
    max_send("delivery");
    sleep(3.0);
    max_send("mix");
  }
  else if (drink.compare("panGalacticGargleBlaster") == 0)
  {
    max_send("This drink produces a sensation not at all unlike having your brain smashed in");
    sleep(6.0);
    max_send("mix");
  }
  else
  {
   std::cout << drink << "is not on the menu\n" << std::endl;
   
   max_send("ERROR: WITTY BANTER NOT FOUND, DO NOT TRUST GLASS CONTENTS");
   sleep(6.0);
   max_send("mix");

  }

}


/*
Taking notes on the cues in lloyd.m4v
0:00- 0:18 Talking Plain
0:18-0:28 Silence
0:28-0:44 Talking Eyebrows
0:44-1:22 Drink mixing
*/
/*Bunting around personality ideas

-Corny robot jokes followed by asking about his delivery
-How do rural robots communicate? EIE-IO

-Sir, you have had too many, I can not serve you another... First law of robotics...

Look to bender for source material

In the future alcoholics anonynmous leads the resistance against drunk-net. Have another drink sir.

-Claim that he's not a robot, make him condesending.

-Marvin lines

Brain the size of an entire fucking planet and I'm here mixing cocktails.

So how did you like that WD-40 spritzer?

The meatbag I replaced.... etc

*/

